package cn.westv.scps.web.utils;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;

/**
 * 验证码生成器
 */

public class ValidateCode {
	// 图片的宽度。
	private int width = 160;
	// 图片的高度。
	private int height = 40;
	// 验证码字符个数
	private int codeCount = 4;
	// 验证码干扰线数
	private int lineCount = 150;
	// 验证码
	private String code = null;
	// 验证码图片Buffer
	private BufferedImage buffImg = null;
	// 字体大小
	private int fontSize = 30;

	Random generator = new Random();

	// private char[] codeSequence = { '0', '1', '2', '3', '4', '5', '6', '7',
	// '8',
	// '9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
	// };
	private char[] codeSequence = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

	public ValidateCode() {
		this.createCode();
	}

	/**
	 * 
	 * @param width
	 *            图片宽
	 * @param height
	 *            图片高
	 */
	public ValidateCode(int width, int height) {
		this.width = width;
		this.height = height;
		this.createCode();
	}

	/**
	 * 
	 * @param width
	 *            图片宽
	 * @param height
	 *            图片高
	 * @param codeCount
	 *            字符个数
	 * @param fontSize
	 *            字体大小
	 * @param lineCount
	 *            干扰线条数
	 */
	public ValidateCode(int width, int height, int codeCount, int fontSize, int lineCount) {
		this.width = width;
		this.height = height;
		if (codeCount != 0)
			this.codeCount = codeCount;
		this.lineCount = lineCount;
		this.fontSize = fontSize;
		this.createCode();
	}

	/**
	 * 产生随机字体
	 * 
	 * @return
	 */
	private Font getFont(int fontSize, int drawFont) {
		Random random = new Random();
		Font font[] = new Font[5];
		font[0] = new Font("Antique Olive Compact", drawFont, fontSize);
		font[1] = new Font("Forte", drawFont, fontSize);
		font[2] = new Font("Times New Roman", drawFont, fontSize);
		font[3] = new Font("Courier", drawFont, fontSize);
		return font[random.nextInt(3)];
		// return font[3];
	}

	/**
	 * 随机产生定义的颜色
	 * 
	 * @return
	 */
	private Color getRandColor() {
		Random random = new Random();
		Color color[] = new Color[10];
		color[0] = new Color(32, 158, 25);
		color[1] = new Color(218, 42, 19);
		color[2] = new Color(31, 75, 208);
		return color[random.nextInt(3)];
	}

	/**
	 * 生成区间内的随机数
	 * 
	 * @param max
	 * @param min
	 * @return
	 */
	private int getRandom(int max, int min) {
		int r = (((int) (Math.random() * max)) + 1) + min;
		return r;
	}

	/**
	 * 生成验证码及图片
	 */
	public void createCode() {
		int x = 0, fontHeight = 0, codeY = 0;
		int red = 0, green = 0, blue = 0;

		x = width / (codeCount + 2);// 每个字符的宽度
		fontHeight = height - 2;// 字体的高度
		codeY = height - 4;

		// 图像buffer
		buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		Graphics2D g = buffImg.createGraphics();
		// 生成随机数
		Random random = new Random();
		// 将图像填充为白色
		g.setColor(Color.WHITE);
		g.fillRect(0, 0, width, height);
		// 创建字体
		// Font mFont = new Font("Times New Roman", Font.CENTER_BASELINE,
		// fontSize);
		Font mFont = getFont(fontSize, 10);

		g.setFont(mFont);

		// shear(g, buffImg.getWidth(), buffImg.getHeight(), Color.BLACK);

		// 添加噪点
		// float yawpRate = 0.07f;// 噪声率
		// int area = (int) (yawpRate * width * height);
		// for (int i = 0; i < area; i++) {
		// int x1 = random.nextInt(width);
		// int y1 = random.nextInt(height);
		// buffImg.setRGB(x1, y1, random.nextInt(255));
		// }
		for (int i = 0; i < lineCount; i++) {
			int xs = random.nextInt(width);
			int ys = random.nextInt(height);
			int xe = xs + random.nextInt(width / 8);
			int ye = ys + random.nextInt(height / 8);
			red = random.nextInt(255);
			green = random.nextInt(255);
			blue = random.nextInt(255);
			g.setColor(new Color(red, green, blue));
			// g.setColor(getRandColor());
			g.drawLine(xs, ys, xe, ye);
		}
		// randomCode记录随机产生的验证码
		StringBuffer randomCode = new StringBuffer();
		// 随机产生codeCount个字符的验证码。
		int random1 = (((int) (Math.random() * (width / 6 - 5))) + 1) + width / 8;
		for (int i = 0; i < codeCount; i++) {
			String strRand = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]);
			// 产生随机的颜色值，让输出的每个字符的颜色值都将不同。
			red = random.nextInt(255);
			green = random.nextInt(255);
			blue = random.nextInt(255);
			g.setColor(new Color(red, green, blue));
			// g.setColor(new Color(31, 75, 208));
			g.drawString(strRand, random1 + i * (width / 5), codeY + random.nextInt(height / 3));
			// 将产生的四个随机数组合在一起。
			randomCode.append(strRand);
		}
		// 将四位数字的验证码保存到Session中。
		code = randomCode.toString();
	}

	private void shear(Graphics g, int w1, int h1, Color color) {

		shearX(g, w1, h1, color);
		shearY(g, w1, h1, color);
	}

	public void shearX(Graphics g, int w1, int h1, Color color) {

		int period = generator.nextInt(2);

		boolean borderGap = true;
		int frames = 1;
		int phase = generator.nextInt(2);

		for (int i = 0; i < h1; i++) {
			double d = (double) (period >> 1)
					* Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
			g.copyArea(0, i, w1, 1, (int) d, 0);
			if (borderGap) {
				g.setColor(color);
				g.drawLine((int) d, i, 0, i);
				g.drawLine((int) d + w1, i, w1, i);
			}
		}

	}

	public void shearY(Graphics g, int w1, int h1, Color color) {

		int period = generator.nextInt(40) + 10; // 50;

		boolean borderGap = true;
		int frames = 20;
		int phase = 7;
		for (int i = 0; i < w1; i++) {
			double d = (double) (period >> 1)
					* Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames);
			g.copyArea(i, 0, 1, h1, 0, (int) d);
			if (borderGap) {
				g.setColor(color);
				g.drawLine(i, (int) d, i, 0);
				g.drawLine(i, (int) d + h1, i, h1);
			}

		}

	}

	/**
	 * 将图片写入文件
	 * 
	 * @param path
	 *            文件地址
	 * @throws IOException
	 */
	public void write(String path) throws IOException {
		File file = new File(path);
		if (!file.exists()) {
			file.createNewFile();
		}
		OutputStream os = new FileOutputStream(path);
		this.write(os);
	}

	/**
	 * 将图片放入输出流
	 * 
	 * @param sos
	 * @throws IOException
	 */
	public void write(OutputStream os) throws IOException {
		ImageIO.write(buffImg, "png", os);
		if (os != null)
			os.close();
	}

	/**
	 * 获取图片缓存对象
	 * 
	 * @return
	 */
	public BufferedImage getBuffImg() {
		return buffImg;
	}

	/**
	 * 获取验证码
	 * 
	 * @return
	 */
	public String getCode() {
		return code;
	}

	public static void main(String[] args) throws IOException {
		for (int i = 0; i < 30; i++) {
			ValidateCode vCode = new ValidateCode(100, 30, 0, 30, 100);
			File file = new File("D:/c/" + vCode.getCode() + ".png");
			if (!file.exists()) {
				file.createNewFile();
			}
			OutputStream out = new FileOutputStream(file);
			vCode.write(out);
			System.out.println(vCode.getCode());
		}
	}

}
